﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Media;
using XamlInspector.Model.Properties;

namespace XamlInspector.Model
{
    public static class PropertyHelper
    {
        public static IEnumerable<XamlProperty> GetProperties(object element, string path = null)
        {
            var properties = new List<XamlProperty>();
            var pathObject = GetElementFromPath(element, path);

            if (pathObject != null)
            {
                properties.AddRange(pathObject.GetType().GetRuntimeProperties().Where(p => p.PropertyType != typeof(DependencyProperty) && p.CanRead)
                    .Select(info => CreateProperty(info, pathObject)));
            }

            return properties;
        }

        private static object GetElementFromPath(object element, string path)
        {
            if (string.IsNullOrWhiteSpace(path))
            {
                return element;
            }

            var chunks = path.Split(new[] { '/', '\\' }, StringSplitOptions.RemoveEmptyEntries);
            object context = element;

            foreach (var chunk in chunks)
            {
                var propertyInfo = context.GetType().GetRuntimeProperties().First(p => p.Name == chunk);
                context = propertyInfo.GetValue(context);
            }

            return context;
        }

        private static XamlProperty CreateProperty(PropertyInfo propertyInfo, object element)
        {
            var type = propertyInfo.PropertyType;
            var typeInfo = type.GetTypeInfo();

            if (typeInfo.IsEnum)
            {
                return new XamlEnumProperty(propertyInfo, element);
            }
            if (type == typeof(bool))
            {
                return new XamlBooleanProperty(propertyInfo, element);
            }
            if (type == typeof(Thickness))
            {
                return new XamlThicknessProperty(propertyInfo, element);
            }
            if (type == typeof(Brush))
            {
                return new XamlBrushProperty(propertyInfo, element);
            }
            if (typeInfo.IsArray || typeof (IEnumerable).GetTypeInfo().IsAssignableFrom(typeInfo))
            {
                // return new XamlListProperty();
            }
            if (typeInfo.IsClass || typeInfo.IsInterface)
            {
                return new XamlCompositeProperty(propertyInfo, element);
            }

            return new XamlProperty(propertyInfo, element);
        }

        public static DependencyProperty GetDependencyProperty(object element, PropertyInfo property)
        {
            var dp = property.DeclaringType.GetRuntimeProperties().FirstOrDefault(p => p.Name == property.Name + "Property");
            if (dp != null)
            {
                return dp.GetValue(element) as DependencyProperty;
            }

            return null;
        }
    }
}
